/*
Copyright 2011 Mary Suárez Machado

Este programa es de software libre: usted puede redistribuirlo y/o modificarlo según los términos de la Licencia de Gran pública de GNU como publicado por la Fundación de Software Libre, versión 3 de la Licencia, (o en su opción) cualquier versión posterior.

 Este programa es distribuido en la esperanza que será útil, pero SIN CUALQUIER GARANTÍA; sin aún la garantía implícita de VALOR COMERCIAL O SALUD PARA UN OBJETIVO PARTICULAR. Mirar la Licencia de Gran pública de GNU para más detalles.
*/


 /**
 *@file LZcoder.cpp
 *@brief Implementaciones de las funciones del módulo LZcoder
 *@author Mary Carmen Suarez
 *
 */

#include <iostream>
#include <fstream>
#include <cassert>
#include <LZcoder.h>

using namespace std;

LZcoder :: LZcoder()
{
	dist_max=0;
	indice=0;
}

LZcoder :: ~LZcoder()
{}

int LZcoder :: GetTamano()const
{
	return cad.Size();
}

void LZcoder :: Leer( istream & is )
{
	cad.Leer(is);
}

int LZcoder :: SiguienteCodigoMejor()
{
    cerr << "\r" << (indice * 100) / GetTamano() << "%";
	if(indice == (GetTamano())) return 256;

	int long_max=0, sig, distancia_maxima=32768,longitud;
	dist_max=-1;
	
	for (int i=indice-1; i>=0 && (indice-i)<=distancia_maxima; i--)
	{
		longitud=0;
		if(cad.GetCaracter(indice) == cad.GetCaracter(i))
		{
			longitud++;
			int distancia=indice - i;
			sig=i+1;
			for (int j=indice+1; j<cad.Size() && cad.GetCaracter(j) == cad.GetCaracter(sig) && longitud<258; j++)
			{
				sig++;
				longitud++;
			}
			if (longitud > long_max)
			{
				long_max=longitud;
				dist_max=distancia;
			}
		}
	}
	indice++;
	if (long_max >= 3)
	{
		indice+=(long_max-1);
		return long_max+256;
	}		
	else
		return (unsigned char)cad.GetCaracter(indice-1);
}

int LZcoder :: SiguienteCodigo()
{
    cerr << "\r" << (indice * 100) / GetTamano() << "%";
	if(indice == (GetTamano())) return 256;

	int sig, distancia_maxima=32768,longitud=0;
	bool controlador=true;
	dist_max = -1;
	
	for (int i=indice-1; controlador==true && i>=0 && (indice-i)<=distancia_maxima; i--)
	{
		longitud=0;
		if(cad.GetCaracter(indice) == cad.GetCaracter(i))
		{
			longitud++;
			int distancia = indice - i;
			sig=i+1;
			for (int j=indice+1; j<cad.Size() && cad.GetCaracter(j) == cad.GetCaracter(sig) && longitud<258; j++)
			{
				sig++;
				longitud++;
			}
			if (longitud >= 3 )
			{
				controlador=false;
				dist_max = distancia;
			}
		}
	}
	if (longitud >= 3)
	{
		indice+=(longitud);
		return longitud+256;
	}		
	else{
		indice++;
		return (unsigned char)cad.GetCaracter(indice-1);
	}
}

int LZcoder :: GetDistancia () const
{
	return dist_max;
}

unsigned int LZcoder :: GetParidad () const
{
	return cad.GetParidad ();
}
